# -*- coding: utf-8 -*-#
import sys
from PySide2 import QtGui, QtCore, QtWidgets
from PySide2.QtWidgets import QApplication, QMainWindow, QDialog
import fitz
from PySide2.QtGui import QImage, QPixmap
import chardet

from mainwindow import Ui_MainWindow
import bookmarkclass as bm
from collections import defaultdict


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        
        # no file opened
        #self.label.setText("打开文件")
        self.bookmark = None
        self.toc_dict = {}
        self.actionOpenInfo.triggered.connect(self.openFile)
        self.actionSaveInfo.triggered.connect(self.saveFile)
        self.actionOpenPDF.triggered.connect(self.openPDF)
        self.actionSavePDF.triggered.connect(self.savePDF)

        self.pInc.clicked.connect(self.page_offset)
        self.minus1.clicked.connect(lambda: self.__offset_page(-1))
        self.minus10.clicked.connect(lambda: self.__offset_page(-10))
        self.minus5.clicked.connect(lambda: self.__offset_page(-5))
        self.add1.clicked.connect(lambda: self.__offset_page(1))
        self.add10.clicked.connect(lambda: self.__offset_page(10))
        self.add5.clicked.connect(lambda: self.__offset_page(5))
        
        #self.treeWidget.currentItemChanged.connect(self.goto_bookmark)
        self.treeWidget.itemSelectionChanged.connect(self.show_selected_bookmark)

        self.op_items = [] # operate on these items
        
        # for pdf   resize
        self.trans_a = 100
        self.trans_b = 100
        self.trans = self.update_trans()
        self.doc = None
        
    def update_trans(self):
        return fitz.Matrix(self.trans_a /100, self.trans_b /100).preRotate(0)

    def openFile(self):
        fname, _ = QtWidgets.QFileDialog.getOpenFileName(filter="bookmark files (*.txt)")
        if not fname:
            return
        self.bookmark = bm.Bookmark()
        self.op_items = [] # operate on these items
        enc = chardet.detect(open(fname, 'rb').read())['encoding']
        print(enc)
        with open(fname, 'r', encoding=enc) as f:
            for l in (f):
                if len(l.strip()) == 0:
                    continue
                self.bookmark.add_line(l)
        #self.bookmark.show()
        self.show_toc()
    def saveFile(self):
        if not self.bookmark:
            return
        fname, _ = QtWidgets.QFileDialog.getSaveFileName(filter="bookmark files (*.txt)")
        if not fname:
            return
        with open(fname, 'w', encoding='utf8') as f:
            f.write(str(self.bookmark))
    
    def page_offset(self):
        offset = self.offset.value()
        self.__offset_page(offset)
        
    def __offset_page(self, offset):
        if offset !=0 and self.bookmark:
            self.logtxt.setHtml('')
            for item in self.op_items:
                bookmark = self.toc_dict[item]
                bookmark.page_tree_inc(offset)
                #self.update_toc(item)
                self.logtxt.insertPlainText(str(bookmark))
            bookmark = self.toc_dict[self.treeWidget.currentItem()]
            self.pdf_page = bookmark.page
            self.pdf_fit()
            self.render_page()
    
    def update_toc(self, current):
        bkmk = self.toc_dict[current]
        current.setText(0, bkmk.title+'\t'+str(bkmk.page))
        for i in current.childCount():
            self.update_toc(current.child(i))
        
    def addbookmark(self, parent, bkmk):
        item = QtWidgets.QTreeWidgetItem(parent, [bkmk.title, str(bkmk.page)])
        self.toc_dict[item] = bkmk
        if parent is None:
            self.topItems.append(item)
        for child in bkmk.children:
            self.addbookmark(item, child)
    def show_toc(self):
        self.treeWidget.clear()
        self.toc_dict.clear()
        if self.bookmark:
            self.topItems = []
            parent = None
            for bkmk in self.bookmark.roots:
                self.addbookmark(None, bkmk)
            self.treeWidget.addTopLevelItems(self.topItems)
            
    def goto_bookmark(self,current, previous):
        self.logtxt.setHtml('')
        if current:
            bookmark = self.toc_dict[current]
            self.pdf_page = bookmark.page
            self.pdf_fit()
            self.render_page()

    def show_selected_bookmark(self):
        self.logtxt.setHtml('')
        # only the top level selected are used 
        # for example if both level 0 and 1 items are selected, L1 items will be ignored
        items_by_level = defaultdict(list)
        top_level = 999 # very unlikely
        for item in self.treeWidget.selectedItems():
            bookmark = self.toc_dict[item]
            items_by_level[bookmark.level].append(item)
            if bookmark.level < top_level:
                top_level = bookmark.level
        self.op_items = items_by_level[top_level]
        for item in self.op_items:
            bookmark = self.toc_dict[item]
            self.logtxt.insertPlainText(f'{str(bookmark)}\n')
        if self.op_items:
            bookmark = self.toc_dict[self.op_items[0]]
            self.pdf_page = bookmark.page
            self.pdf_fit()
            self.render_page()
    def openPDF(self):
        pdfname, _ = QtWidgets.QFileDialog.getOpenFileName(filter="pdf files (*.pdf)")
        if not pdfname:
            return
        self.doc = fitz.open(pdfname)
        self.num_pages = self.doc.page_count
        self.prepare_toc()
        self.show_toc()
        self.pdf_page =1
        self.pdf_fit()
        self.render_page()
    
    def prepare_toc(self):
        # read toc from pdf file
        self.pdf_toc = self.doc.get_toc()
        self.bookmark = bm.Bookmark()
        for levelplus1, title, page in self.pdf_toc:
            level = levelplus1-1
            self.bookmark.add_item(level, title, page)
        
    def pdf_fit(self):
        pageHeight = self.getCurrentPage().cropbox.height
        viewHeight = self.pdfPreview.size().height() # same height with logtxt
        self.trans_a = viewHeight/pageHeight*100
        self.trans_b = self.trans_a
        self.trans = self.update_trans()

    def getCurrentPage(self):
        return self.doc[self.pdf_page-1]

    def render_page(self):
        # read current page
        pix	= self.getCurrentPage().get_pixmap(matrix = self.trans)
        pngdata = pix.getPNGdata()
        #print(pngdata, len(pngdata))
        qpix = QPixmap()
        qpix.loadFromData(QtCore.QByteArray(pngdata))
        self.pdfPreview.setPixmap(qpix)


    def savePDF(self):
        if not self.doc:
            print('无PDF文件。')
            return
        toc = []
        for bkmk in self.bookmark.roots:
            for level, title, page in bkmk.to_list():
                toc.append([level+1, title, min(page, self.doc.page_count)])
        self.doc.set_toc(toc)
        pdfname, _ = QtWidgets.QFileDialog.getSaveFileName(filter="PDF files (*.pdf)")
        if not pdfname:
            return
        self.doc.save(pdfname)
        print('完成书签写入。')


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
